<?php
/**
 * SocialEngine
 *
 * @category   Application_Core
 * @package    Storage
 * @copyright  Copyright 2006-2010 Webligo Developments
 * @license    http://www.socialengine.net/license/
 * @version    $Id: Abstract.php 8415 2011-02-09 03:30:20Z john $
 * @author     John Boehr <j@webligo.com>
 */

/**
 * @category   Application_Core
 * @package    Storage
 * @copyright  Copyright 2006-2010 Webligo Developments
 * @license    http://www.socialengine.net/license/
 */
abstract class Storage_Service_Abstract implements Storage_Service_Interface {
	protected $_identity;
	
	protected $_scheme;
	
	protected $_schemeClass = 'Storage_Service_Scheme_Dynamic';
	
	// General
	

	public function __construct(array $config = array()) {
		if (! empty ( $config ['service_id'] )) {
			$this->_identity = $config ['service_id'];
		}
	}
	
	public function getIdentity() {
		return $this->_identity;
	}
	
	// Scheme
	

	public function getScheme() {
		if (null === $this->_scheme) {
			$class = $this->_schemeClass;
			$this->_scheme = new $class ();
		}
		
		return $this->_scheme;
	}
	
	public function setScheme(Storage_Service_Scheme_Interface $scheme) {
		$this->_scheme = $scheme;
		return $this;
	}
	
	/* Utility */
	
	public function getBaseUrl() {
		return $this->_removeScriptName ( Zend_Controller_Front::getInstance ()->getBaseUrl () );
	}
	
	public function fileInfo($file) {
		// $file is an instance of Zend_Form_Element_File
		if ($file instanceof Zend_Form_Element_File) {
			$info = $file->getFileInfo ();
			$info = current ( $info );
		} 

		// $file is a key of $_FILES
		else if (is_array ( $file )) {
			$info = $file;
		} 

		// $file is a string
		else if (is_string ( $file )) {
			$info = array ('tmp_name' => $file, 'name' => basename ( $file ), 'type' => 'unknown/unknown', // @todo
'size' => filesize ( $file ) );
			
			// Try to get image info
			if (function_exists ( 'getimagesize' ) && ($imageinfo = getimagesize ( $file ))) {
				$info ['type'] = $imageinfo ['mime'];
			}
		} 

		// $file is an unknown type
		else {
			throw new Storage_Service_Exception ( 'Unknown file type specified' );
		}
		
		// Check to make sure file exists and not security problem
		self::_checkFile ( $info ['tmp_name'], 04 ); // Check for read
		

		// Do some other stuff
		$mime_parts = explode ( '/', $info ['type'], 2 );
		$info ['mime_major'] = $mime_parts [0];
		$info ['mime_minor'] = $mime_parts [1];
		$info ['hash'] = md5_file ( $info ['tmp_name'] );
		$info ['extension'] = ltrim ( strrchr ( $info ['name'], '.' ), '.' );
		unset ( $info ['type'] );
		
		return $info;
	}
	
	protected function _removeScriptName($url) {
		if (! isset ( $_SERVER ['SCRIPT_NAME'] )) {
			// We can't do much now can we? (Well, we could parse out by ".")
			return $url;
		}
		
		if (($pos = strripos ( $url, basename ( $_SERVER ['SCRIPT_NAME'] ) )) !== false) {
			$url = substr ( $url, 0, $pos );
		}
		
		return $url;
	}
	
	protected function _checkFile($file, $mode = 06) {
		// @todo This is fubared, fix up later
		//if( preg_match('/[^a-z0-9\\/\\\\_.:-]/i', $file) )
		//if( preg_match('/[^a-z0-9 \\/\\\\_.:-]/i', $file) )
		//{
		//throw new Storage_Service_Exception(sprintf('Security check: Illegal character in filename: %s', $file));
		//}
		

		if ($mode && ! file_exists ( $file )) {
			throw new Storage_Service_Exception ( 'File does not exist: ' . $file );
		}
		
		if (($mode & 04) && (! is_readable ( $file ))) {
			throw new Storage_Service_Exception ( 'File not readable: ' . $file );
		}
		
		if (($mode & 02) && (! is_writable ( $file ))) {
			throw new Storage_Service_Exception ( 'File not writeable: ' . $file );
		}
		
		if (($mode & 01) && (! is_executable ( $file ))) {
			throw new Storage_Service_Exception ( 'File not executable: ' . $file );
		}
	}
	
	protected function _mkdir($path, $mode = 0777) {
		// Change umask
		if (function_exists ( 'umask' )) {
			$oldUmask = umask ();
			umask ( 0 );
		}
		
		// Change perms
		$code = 0;
		if (is_dir ( $path )) {
			@chmod ( $path, $mode );
		} else if (! @mkdir ( $path, $mode, true )) {
			$code = 1;
		}
		
		// Revert umask
		if (function_exists ( 'umask' )) {
			umask ( $oldUmask );
		}
		
		// Respond
		if (1 == $code) {
			throw new Storage_Service_Exception ( sprintf ( 'Could not create folder: %s', $path ) );
		}
	}
	
	protected function _move($from, $to) {
		// Change umask
		if (function_exists ( 'umask' )) {
			$oldUmask = umask ();
			umask ( 0 );
		}
		
		// Move
		$code = 0;
		if (! is_file ( $from )) {
			$code = 1;
		} else if (! @rename ( $from, $to )) {
			@mkdir ( dirname ( $to ), 0777, true );
			if (! @rename ( $from, $to )) {
				$code = 1;
			}
		}
		
		// Revert umask
		if (function_exists ( 'umask' )) {
			umask ( $oldUmask );
		}
		
		if (1 == $code) {
			throw new Storage_Service_Exception ( 'Unable to move file (' . $from . ') -> (' . $to . ')' );
		}
	}
	
	protected function _delete($file) {
		// Delete
		$code = 0;
		if (is_file ( $file )) {
			if (! @unlink ( $file )) {
				@chmod ( $file, 0777 );
				if (! @unlink ( $file )) {
					$code = 1;
				}
			}
		}
		
		if (1 == $code) {
			throw new Storage_Service_Exception ( 'Unable to delete file: ' . $file );
		}
	}
	
	protected function _copy($from, $to) {
		// Change umask
		if (function_exists ( 'umask' )) {
			$oldUmask = umask ();
			umask ( 0 );
		}
		
		// Copy
		$code = 0;
		if (! is_file ( $from )) {
			$code = 1;
		} else if (! @copy ( $from, $to )) {
			@mkdir ( dirname ( $to ), 0777, true );
			@chmod ( dirname ( $to ), 0777 );
			if (! @copy ( $from, $to )) {
				$code = 1;
			}
		}
		
		// Revert umask
		if (function_exists ( 'umask' )) {
			umask ( $oldUmask );
		}
		
		if (1 == $code) {
			throw new Storage_Service_Exception ( 'Unable to copy file (' . $from . ') -> (' . $to . ')' );
		}
	}
	
	protected function _write($file, $data) {
		// Change umask
		if (function_exists ( 'umask' )) {
			$oldUmask = umask ();
			umask ( 0 );
		}
		
		// Write
		$code = 0;
		if (! @file_put_contents ( $file, $data )) {
			if (is_file ( $file )) {
				@chmod ( $file, 0666 );
			} else if (is_dir ( dirname ( $file ) )) {
				@chmod ( dirname ( $file ), 0777 );
			} else {
				@mkdir ( dirname ( $file ), 0777, true );
			}
			
			if (! @file_put_contents ( $file, $data )) {
				$code = 1;
			}
		}
		
		// Revert umask
		if (function_exists ( 'umask' )) {
			umask ( $oldUmask );
		}
		
		if (1 == $code) {
			throw new Storage_Service_Exception ( sprintf ( 'Unable to write to file: $s', $file ) );
		}
	}
	
	protected function _read($file) {
		if (! @file_get_contents ( $file )) {
			throw new Storage_Service_Exception ( 'Unable to read file: ' . $file );
		}
	}
}
